using FishFillets.Model;
using FishFillets.Model.GameItems;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using FishFillets.GameComponents.Helpers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;

namespace FishFillets.GameComponents
{
    public class FishComponent : BaseItemComponent
    {
        private readonly Fish fish;

        public FishComponent(Game game, ContentManager contentManager, AssetHelper contentAltManager, Fish fish, string name) 
            : base(game, contentManager, contentAltManager, name)
        {
            this.fish = fish;
        }
        
        protected override void LoadContent()
        {
            LoadFishTexturesByAnimName(name, FishDirection.Left, "body", "rest", 3);
            LoadFishTexturesByAnimName(name, FishDirection.Left, "body", "skeleton", 1);
            LoadFishTexturesByAnimName(name, FishDirection.Left, "body", "swam", 6);
            LoadFishTexturesByAnimName(name, FishDirection.Left, "body", "talk", 3);
            LoadFishTexturesByAnimName(name, FishDirection.Left, "body", "turn", 3);
            LoadFishTexturesByAnimName(name, FishDirection.Left, "body", "vertical", 6);

            LoadFishTexturesByAnimName(name, FishDirection.Right, "body", "rest", 3);
            LoadFishTexturesByAnimName(name, FishDirection.Right, "body", "skeleton", 1);
            LoadFishTexturesByAnimName(name, FishDirection.Right, "body", "swam", 6);
            LoadFishTexturesByAnimName(name, FishDirection.Right, "body", "talk", 3);
            LoadFishTexturesByAnimName(name, FishDirection.Right, "body", "turn", 3);
            LoadFishTexturesByAnimName(name, FishDirection.Right, "body", "vertical", 6);
            if (fish.Direction == FishDirection.Left)
                texture = texturesDirLeft["body_rest_00"];
            else
                texture = texturesDirRight["body_rest_00"];

            drawPosition = new Vector2(fish.Position.X * Common.BlockWidth, fish.Position.Y * Common.BlockHeight);
        }

        protected void LoadFishTexturesByAnimName(string fishName,
            FishDirection direction, string textureName, string animationName, int framesCount)
        {
            string strDir;
            Dictionary<string, Texture2D> targetDict;
            switch (direction){
                case FishDirection.Left:
                    strDir = "left";
                    targetDict = texturesDirLeft;
                    break;
                case FishDirection.Right:
                    strDir = "right";
                    targetDict = texturesDirRight;
                    break;
                default:
                    throw new ArgumentException("direction");
            }

            for (int i = 0; i < framesCount; i++)
            {
                string texName = String.Format("{0}_{1}_{2:00}", textureName, animationName, i);
                targetDict.Add(texName, contentAltManager.LoadTextureStream(
                    Path.Combine(
                    String.Format("images/fishes/{0}/{1}", fishName, strDir),
                    texName)));
            }
        }

        public override void Update(GameTime gameTime)
        {
            Dictionary<string, Texture2D> chosenTexSource = null;
            string texName = null;

            switch (fish.Direction)
            {
                case FishDirection.Left:
                    chosenTexSource = texturesDirLeft;
                    break;
                case FishDirection.Right:
                    chosenTexSource = texturesDirRight;
                    break;
            }

            // spaghetti code
            if (isMoving)
            {
                // TODO: clearly does not work as expected
                switch(AnimFrame) {
                    case 0:
                        drawPosition = Vector2.SmoothStep(drawPosition,
                            new Vector2(fish.Position.X * Common.BlockWidth, fish.Position.Y * Common.BlockHeight),
                            0.3f);
                        texName = String.Format("{0}_{1}_{2:00}", "body", "swam", AnimFrame);
                        AnimFrame++;
                        break;
                    case 1:
                        drawPosition = Vector2.SmoothStep(drawPosition,
                            new Vector2(fish.Position.X * Common.BlockWidth, fish.Position.Y * Common.BlockHeight),
                            0.5f);
                        texName = String.Format("{0}_{1}_{2:00}", "body", "swam", AnimFrame);
                        AnimFrame++;
                        break;
                    case 2:
                        texName = String.Format("{0}_{1}_{2:00}", "body", "swam", AnimFrame);
                        AnimFrame = 0;
                        break;
                }

            }
            else if (isTurningAround) // when fish turns around
            {
                AnimFrameCount = 3; // TODO: this number should be saved somewhere else I think
                texName = String.Format("{0}_{1}_{2:00}", "body", "turn", AnimFrame);

                if (AnimFrame < AnimFrameCount - 1)
                    AnimFrame++;
                else
                {
                    isTurningAround = false;
                }
            }
            else if (fish.Talking)
            {
                // TODO: talking as normal or busy talk? Need to overlay fishes' head
                switch (AnimFrame)
                {
                    case 0:
                        texName = String.Format("{0}_{1}_{2:00}", "body", "talk", AnimFrame);
                        AnimFrame++;
                        break;
                    case 1:
                        texName = String.Format("{0}_{1}_{2:00}", "body", "talk", AnimFrame);
                        AnimFrame++;
                        break;
                    case 2:
                        texName = String.Format("{0}_{1}_{2:00}", "body", "talk", AnimFrame);
                        AnimFrame = 0;
                        break;
                }
            }
            else
            {
                drawPosition = new Vector2(fish.Position.X * Common.BlockWidth, fish.Position.Y * Common.BlockHeight);

                AnimFrameCount = 3; // TODO: this number should be saved somewhere else I think
                texName = String.Format("{0}_{1}_{2:00}", "body", "rest", AnimFrame);
                
                if (AnimFrame < AnimFrameCount - 1)
                    AnimFrame++;
                else
                    AnimFrame = 0;
            }

            texture = chosenTexSource[texName];
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            int width = fish.ItemMap.GetLength(0) * Common.BlockWidth;
            int height = fish.ItemMap.GetLength(1) * Common.BlockHeight;
            SpriteBatch.Draw(texture, drawPosition, null, fish.Active ? Color.Orange : Color.White, 0f,
                Vector2.Zero, 1f, SpriteEffects.None, 0.4f);
        }
    }
}
